package extractfields;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Vector;


public class AnalyzeObject {
	
	private static AnalyzeObject Instance = null;

	public static AnalyzeObject getInstance() 
	{
		if(null == Instance) {
			Instance = new AnalyzeObject();
		} 
		
		return Instance;
	}
	
	
	private static String processDisplayPrimitiveArray( Class c, Object valueObj, String separator) {

		String result = new String("");
		if (c.equals(char[].class)) {
			char[] charArray = new char[((char[]) valueObj).length];

			System.arraycopy(valueObj, 0, charArray, 0, charArray.length);
			String s = new String(charArray);
			result =  s;
		} else if (c.equals(byte[].class)) {
			byte[] byteArray = new byte[((byte[]) valueObj).length];

			System.arraycopy(valueObj, 0, byteArray, 0, byteArray.length);
			for (byte i : byteArray)
				result += (byte) i + separator;

		} else if (c.equals(int[].class)) {
			int[] intArray = new int[((int[]) valueObj).length];
			System.arraycopy(valueObj, 0, intArray, 0, intArray.length);
			for (int i : intArray)
				result += i + separator;
		} else if (c.equals(short[].class)) {
			short[] shortArray = new short[((short[]) valueObj).length];
			System.arraycopy(valueObj, 0, shortArray, 0, shortArray.length);
			for (short i : shortArray)
				result += i + separator;
		} else if (c.equals(boolean[].class)) {
			boolean[] booleanArray = new boolean[((boolean[]) valueObj).length];
			System.arraycopy(valueObj, 0, booleanArray, 0, booleanArray.length);
			for (boolean i : booleanArray)
				result += i + separator;
		} else if (c.equals(float[].class)) {
			float[] floatArray = new float[((float[]) valueObj).length];
			System.arraycopy(valueObj, 0, floatArray, 0, floatArray.length);
			for (float i : floatArray)
				result += i + separator;
		}else if (c.equals(double[].class)) {
			double[] doubleArray = new double[((double[]) valueObj).length];
			System.arraycopy(valueObj, 0, doubleArray, 0, doubleArray.length);
			for (double i : doubleArray)
				result += i + separator;
		}else {
			result +=  "Array";
		}	
		return result;

	}

	 public static String variableIntoString(Object value, String separatorArray) throws IllegalArgumentException, IllegalAccessException {
		 
		 String result = "";

		 if (value == null) {
			 result = "null";
		 } else {
			 boolean isPrimitive = value.getClass().isPrimitive();
			 
	        if (value.getClass().isPrimitive() ||
	                value.getClass() == java.lang.Short.class ||
	                value.getClass() == java.lang.Long.class ||
	                value.getClass() == java.lang.String.class ||
	                value.getClass() == java.lang.Integer.class ||
	                value.getClass() == java.lang.Float.class ||
	                value.getClass() == java.lang.Byte.class ||
	                value.getClass() == java.lang.Character.class ||
	                value.getClass() == java.lang.Double.class ||
	                value.getClass() == java.lang.Boolean.class) 
	        {
	        	result =  value.toString();
	        	
	        } else if (value.getClass().isArray()) {
	        	
				result = processDisplayPrimitiveArray(value.getClass(),value,"");
			 
	        } else if(value.getClass().getSuperclass().equals(Number.class)) {

	        	result =((Number)value).toString();
	        	
			 } else{

				 result = String.valueOf(value);
			 
			 }
		 }

		 return result;
	 }

	 private static int getIndexFromArray( String fieldArray) {
		 
		 int retVal = -1;
		 
		 int openSquare = fieldArray.indexOf("[");
		 int endSquare = fieldArray.indexOf("]");
		 String appo = fieldArray.substring(openSquare + 1, endSquare );
		 
		 Integer valInteger = new Integer(appo);
		 retVal = valInteger.intValue();
		 
		 return retVal;
		 
	 }

	 
	 
	 private static void printFields(Class<?> cls) {
	
			Field[] fields = cls.getDeclaredFields();

			for (Field field : fields) {
				
				final String fieldName = field.getName();
				final String fieldTypeName = field.getType().getName();
				
				Class<?> entry = field.getType();
					
					
				if (fieldName.startsWith("[L")) {
					try {
						entry = Class.forName( fieldTypeName.replaceFirst("\\[L", "").replaceFirst(";$", ""));
					} catch (ClassNotFoundException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
					
				System.out.println("fieldName = " + fieldName + " \n\tfieldTypeName = " + fieldTypeName +"\n\tentry = " + entry);
					
				
			}

	 }
	 
		public static Map<String, String> analyzeObject( final Vector<String> fieldToExtract, Object obj) 
		{
			Map<String, String> mapFieldValue = new HashMap< String, String>();

			Class  aClass = obj.getClass();
	    	// printFields(aClass);
			
			for (Iterator iter = fieldToExtract.iterator(); iter.hasNext();) {
			    StringBuffer buffer = new StringBuffer();

			    String fieldName = (String) iter.next();
				// System.out.println("analyzeObject : fieldName  = [" + fieldName +"]" );

				// Init the value in the map
				mapFieldValue.put(fieldName, "null");

		        String props[] = fieldName.split("\\.");  
		        Field field = null;
		        Object  fo = null;
		        
				try {

					String fieldAppo = props[0];
					int indexArray = -1;
					
					int openSquare = fieldAppo.indexOf("[");
					
					if (0 < openSquare) {
						indexArray = getIndexFromArray(fieldAppo);
						
						fieldAppo = fieldAppo.substring(0, openSquare - 1);
					}
					
					field = aClass.getField( fieldAppo );
					fo = field.get(obj);
					
					
			        for (int i = 1; i < props.length; i++) {
			        	
			        	fieldAppo = props[i];
						openSquare = fieldAppo.indexOf("[");
						
						if (0 < openSquare) {
							indexArray = getIndexFromArray(fieldAppo);
							
							fieldAppo = fieldAppo.substring(0, openSquare );
						}

						int openRound = fieldAppo.indexOf("(");
						if (0 < openRound) {
							fieldAppo = fieldAppo.substring(0, openRound );
						}
			        	
			        	Class fieldClass = field.getType();
			        	// printFields(fieldClass);
			        	
			    	    if (fieldClass.isArray()) {

			    	    	fo = Array.get(fo, indexArray);
			    	    	fieldClass = fo.getClass();
				        	// printFields(fieldClass);

			    	    	
			    	    }
			        	
						field = fieldClass.getDeclaredField( fieldAppo);
						field.setAccessible(true);
						fo = field.get(fo);
			        	
			        }

			        // field = aClass.getField( fieldName );
			        String fieldValue = variableIntoString(fo, "");
					mapFieldValue.put(fieldName, fieldValue);
					
					// System.out.println("analyzeObject : fieldName  = [" + fieldName +"] fieldValue  = [" + fieldValue +"]" );
					
				} catch (SecurityException e) {
					System.out.println("analyzeObject : SecurityException  = [" + e.getMessage() +"]" );
				} catch (NoSuchFieldException e) {
					System.out.println("analyzeObject : NoSuchFieldException  = [" + e.getMessage() +"]" );
				} catch (IllegalArgumentException e) {
					System.out.println("analyzeObject : IllegalArgumentException  = [" + e.getMessage() +"]" );
				} catch (IllegalAccessException e) {
					System.out.println("analyzeObject : IllegalAccessException  = [" + e.getMessage() +"]" );
				}
				
			}
			
			
			return mapFieldValue;
		}
	 
	 
	public static Map<String, Object> analyzeObject2( final Vector<String> fieldToExtract, Object obj) 
	{
		Map<String, Object> mapFieldValue = new HashMap< String, Object>();

		Class  aClass = obj.getClass();
    	// printFields(aClass);
		
		for (Iterator iter = fieldToExtract.iterator(); iter.hasNext();) {
		    StringBuffer buffer = new StringBuffer();

		    String fieldName = (String) iter.next();
			System.out.println("analyzeObject : fieldName  = [" + fieldName +"]" );

			// Init the value in the map
			mapFieldValue.put(fieldName, "null");

	        String props[] = fieldName.split("\\.");  
	        Field field = null;
	        Object  fo = null;
	        
			try {

				String fieldAppo = props[0];
				
				int openSquare = fieldAppo.indexOf("[");
				
				field = aClass.getField( fieldAppo );
				fo = field.get(obj);
				
				mapFieldValue.put(fieldName, fo);
				
				System.out.println("analyzeObject : fieldName  = [" + fieldName +"] fieldValue  = [" + buffer.toString() +"]" );
				
			} catch (SecurityException e) {
				System.out.println("analyzeObject : SecurityException  = [" + e.getMessage() +"]" );
			} catch (NoSuchFieldException e) {
				System.out.println("analyzeObject : NoSuchFieldException  = [" + e.getMessage() +"]" );
			} catch (IllegalArgumentException e) {
				System.out.println("analyzeObject : IllegalArgumentException  = [" + e.getMessage() +"]" );
			} catch (IllegalAccessException e) {
				System.out.println("analyzeObject : IllegalAccessException  = [" + e.getMessage() +"]" );
			}
			
		}
		
		
		return mapFieldValue;
	}

	public static Vector<FieldValue> analyzeObject3( final Vector<String> fieldToExtract, Object obj) 
	{
		Vector<FieldValue> mapFieldValue = new Vector<FieldValue>();

		Class  aClass = obj.getClass();
    	// printFields(aClass);
		
		for (Iterator iter = fieldToExtract.iterator(); iter.hasNext();) {
		    StringBuffer buffer = new StringBuffer();

		    String fieldName = (String) iter.next();
			System.out.println("analyzeObject : fieldName  = [" + fieldName +"]" );

			// Init the value in the map
			FieldValue fv = new FieldValue(fieldName, "null", String.class);

	        String props[] = fieldName.split("\\.");  
	        Field field = null;
	        Object  fo = null;
	        
			try {

				String fieldAppo = props[0];
				int indexArray = -1;
				
				int openSquare = fieldAppo.indexOf("[");
				
				if (0 < openSquare) {
					indexArray = getIndexFromArray(fieldAppo);
					
					fieldAppo = fieldAppo.substring(0, openSquare - 1);
				}
				
				field = aClass.getField( fieldAppo );
				fo = field.get(obj);
				
				
		        for (int i = 1; i < props.length; i++) {
		        	
		        	fieldAppo = props[i];
					openSquare = fieldAppo.indexOf("[");
					
					if (0 < openSquare) {
						indexArray = getIndexFromArray(fieldAppo);
						
						fieldAppo = fieldAppo.substring(0, openSquare );
					}

					int openRound = fieldAppo.indexOf("(");
					if (0 < openRound) {
						fieldAppo = fieldAppo.substring(0, openRound );
					}
		        	
		        	Class fieldClass = field.getType();
		        	// printFields(fieldClass);
		        	
		    	    if (fieldClass.isArray()) {

		    	    	fo = Array.get(fo, indexArray);
		    	    	fieldClass = fo.getClass();
			        	printFields(fieldClass);

		    	    	
		    	    }
		        	
					field = fieldClass.getDeclaredField( fieldAppo);
					field.setAccessible(true);
					fo = field.get(fo);


		        }


		        // field = aClass.getField( fieldName );
		        String fieldValue = "";
		        if(props.length > 1) {
					buffer.append( fo);
		        	
		        } else {
					buffer.append( variableIntoString(obj, ""));
		        	
		        }
		        
		        fv.setFieldClass(field.getClass());
		        fv.setFieldName(fieldName);
		        fv.setFieldValue(buffer.toString());
		        
		        mapFieldValue.add( fv);
		        
				
				System.out.println("analyzeObject : fieldName  = [" + fieldName +"] fieldValue  = [" + buffer.toString() +"]" );
				
			} catch (SecurityException e) {
				System.out.println("analyzeObject : SecurityException  = [" + e.getMessage() +"]" );
			} catch (NoSuchFieldException e) {
				System.out.println("analyzeObject : NoSuchFieldException  = [" + e.getMessage() +"]" );
			} catch (IllegalArgumentException e) {
				System.out.println("analyzeObject : IllegalArgumentException  = [" + e.getMessage() +"]" );
			} catch (IllegalAccessException e) {
				System.out.println("analyzeObject : IllegalAccessException  = [" + e.getMessage() +"]" );
			}
			
		}
		
		
		return mapFieldValue;
	}
	
}
